#ifndef _SYS_MAP_H_
#define _SYS_MAP_H_

#include "FanObj.h"
#include "SysTypes.h"

#define MAP_VTABLE(self)   ((MapVTable*)((FanObj*)self)->vtable)


extern Type*    Map_classType;
extern VTable*  Map_classVTable;


/* [sys::Map] Attributes */
struct Map
{
  FanObj        super;
};


/* [sys::Map] Iterator */
struct MapIterator
{
  Val           key;
  Val           val;
};


/* [sys::Map] Virtual-table */
typedef struct MapVTable
{
  FanObjVTable  super;
} MapVTable;


/* [sys::Map] Methods and fields */
void            Map_make(Map* self, Type* type);
Bool            Map_equals(Obj self, NullableObj that);
Int             Map_hash(Obj self);
Str*            Map_toStr(Obj self);
Bool            Map_caseInsensitive(Map* self);
void            Map_setCaseInsensitive(Map* self, Bool val);
Bool            Map_ordered(Map* self);
void            Map_setOrdered(Map* self, Bool val);
Val             Map_def(Map* self);
void            Map_setDef(Map* self, Val val);
Bool            Map_isEmpty(Map* self);
Int             Map_size(Map* self);
Val             Map_get_1(Map* self, Val key);
Val             Map_get(Map* self, Val key, Val def);
Bool            Map_containsKey(Map* self, Val key);
List*           Map_keys(Map* self);
List*           Map_vals(Map* self);
Map*            Map_dup(Map* self);
Map*            Map_set(Map* self, Val key, Val val);
Map*            Map_add(Map* self, Val key, Val val);
Val             Map_getOrAdd(Map* self, Val key, Func* valFunc);
Map*            Map_setAll(Map* self, Map* m);
Map*            Map_addAll(Map* self, Map* m);
Map*            Map_setList_1(Map* self, List* list);
Map*            Map_setList(Map* self, List* list, Func* c);
Map*            Map_addList_1(Map* self, List* list);
Map*            Map_addList(Map* self, List* list, Func* c);
Val             Map_remove(Map* self, Val key);
Map*            Map_clear(Map* self);
Str*            Map_join_1(Map* self, Str* separator);
Str*            Map_join(Map* self, Str* separator, Func* c);
Str*            Map_toCode(Map* self);
void            Map_each(Map* self, Func* c);
NullableObj     Map_eachWhile(Map* self, Func* c);
Val             Map_find(Map* self, Func* c);
Map*            Map_findAll(Map* self, Func* c);
Map*            Map_exclude(Map* self, Func* c);
Bool            Map_any(Map* self, Func* c);
Bool            Map_all(Map* self, Func* c);
NullableObj     Map_reduce(Map* self, NullableObj init, Func* c);
Map*            Map_map(Map* self, Func* c);
Bool            Map_isRO(Map* self);
Bool            Map_isRW(Map* self);
Map*            Map_ro(Map* self);
Map*            Map_rw(Map* self);


/* [sys::Map] Extra methods */
Map*            Map_new(Type* keyType, Type* valType);
MapIterator*    Map_iterator(Map* self);
MapIterator*    Map_iteratorAdvance(MapIterator* it);


/* [sys::Map] Type-system functions */
Type*           Map_initType(void);
VTable*         Map_initVTable(void);
void            Map_initStatic(void);


#endif
